package com.redis.config;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Redis 基础配置
 * @author YI
 * @date 2018-1-12
 */
@Component
@EnableCaching
@Configuration
@PropertySource("classpath:config/redis.properties")
public class JedisCongfig {
    public static Log log = LogFactory.get();

    /**
     * 地址，默认localhost
     */
    private static String host;

    /**
     * 端口，默认6379
     */
    private static int port;

    /**
     * 超时，默认2000
     */
    private static int timeout;

    /**
     * 密码，默认无
     */
    private static String password;

    /**
     * 数据库序号，默认0
     */
    private static int database;

    /**
     * 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
     */
    private static boolean blockWhenExhausted;

    /**
     * 是否启用pool的jmx管理功能, 默认true
     */
    private static boolean jmxEnabled;

    /**
     * 是否启用后进先出, 默认true
     */
    private static boolean lifo;

    /**
     * 最大空闲连接数, 默认8个
     */
    private static int maxIdle;

    /**
     * 最小空闲连接数, 默认0
     */
    private static int minIdle;

    /**
     * 最大连接数, 默认8个
     */
    private static int maxTotal;

    /**
     * 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1
     */
    private static long maxWaitMillis;

    /**
     * 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
     */
    private static long minEvictableIdleTimeMillis;

    /**
     * 每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
     */
    private static int numTestsPerEvictionRun;

    /**
     * 对象空闲多久后逐出, 当空闲时间>该值 且 空闲连接>最大空闲数 时直接逐出,不再根据MinEvictableIdleTimeMillis判断  (默认逐出策略)
     */
    private static long softMinEvictableIdleTimeMillis;

    /**
     * 在获取连接的时候检查有效性, 默认false
     */
    private static boolean testOnBorrow;

    /**
     * 在空闲时检查有效性, 默认false
     */
    private static boolean testWhileIdle;

    /**
     * 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
     */
    private static long timeBetweenEvictionRunsMillis;

    private static JedisPool jedisPool = null;

    /**
     * 初始化Redis连接池
     */
    public static void initJedisPool(){
        try {
            JedisPoolConfig config = new JedisPoolConfig();

            config.setMaxTotal(maxTotal);
            config.setMaxIdle(maxIdle);
            config.setMaxWaitMillis(maxWaitMillis);
            config.setMinIdle(minIdle);
            config.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
            config.setTestOnBorrow(testOnBorrow);
            config.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
            config.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis);
            config.setTestWhileIdle(testWhileIdle);
            config.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
            config.setLifo(lifo);
            config.setBlockWhenExhausted(blockWhenExhausted);
            config.setJmxEnabled(jmxEnabled);

            if (StrUtil.isBlank(password)){
                //无密码
                jedisPool = new JedisPool(config, host, port, timeout);
            }else {
                //有密码
                jedisPool = new JedisPool(config, host, port, timeout, password, database);
            }

            log.info("Redis连接池信息{}",JSONUtil.parse(jedisPool.getResource()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取Jedis实例
     * @return
     */
    public synchronized static Jedis getJedis() {
        initJedisPool();
        try {
            if (jedisPool != null) {
                Jedis jedis = jedisPool.getResource();
                return jedis;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 释放jedis资源
     * @param jedis
     */
    public static void returnJedis(final Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }

    @Value("${host}")
    public void setHost(String host) {
        JedisCongfig.host = host;
    }

    @Value("${port}")
    public void setPort(int port) {
        JedisCongfig.port = port;
    }

    @Value("${timeout}")
    public void setTimeout(int timeout) {
        JedisCongfig.timeout = timeout;
    }

    @Value("${password}")
    public void setPassword(String password) {
        JedisCongfig.password = password;
    }

    @Value("${database}")
    public void setDatabase(int database) {
        JedisCongfig.database = database;
    }

    @Value("${blockWhenExhausted}")
    public void setBlockWhenExhausted(boolean blockWhenExhausted) {
        JedisCongfig.blockWhenExhausted = blockWhenExhausted;
    }

    @Value("${jmxEnabled}")
    public void setJmxEnabled(boolean jmxEnabled) {
        JedisCongfig.jmxEnabled = jmxEnabled;
    }

    @Value("${lifo}")
    public void setLifo(boolean lifo) {
        JedisCongfig.lifo = lifo;
    }

    @Value("${maxIdle}")
    public void setMaxIdle(int maxIdle) {
        JedisCongfig.maxIdle = maxIdle;
    }

    @Value("${minIdle}")
    public void setMinIdle(int minIdle) {
        JedisCongfig.minIdle = minIdle;
    }

    @Value("${maxTotal}")
    public void setMaxTotal(int maxTotal) {
        JedisCongfig.maxTotal = maxTotal;
    }

    @Value("${maxWaitMillis}")
    public void setMaxWaitMillis(long maxWaitMillis) {
        JedisCongfig.maxWaitMillis = maxWaitMillis;
    }

    @Value("${minEvictableIdleTimeMillis}")
    public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
        JedisCongfig.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
    }

    @Value("${numTestsPerEvictionRun}")
    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
        JedisCongfig.numTestsPerEvictionRun = numTestsPerEvictionRun;
    }

    @Value("${softMinEvictableIdleTimeMillis}")
    public void setSoftMinEvictableIdleTimeMillis(long softMinEvictableIdleTimeMillis) {
        JedisCongfig.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
    }

    @Value("${testOnBorrow}")
    public void setTestOnBorrow(boolean testOnBorrow) {
        JedisCongfig.testOnBorrow = testOnBorrow;
    }

    @Value("${testWhileIdle}")
    public void setTestWhileIdle(boolean testWhileIdle) {
        JedisCongfig.testWhileIdle = testWhileIdle;
    }

    @Value("${timeBetweenEvictionRunsMillis}")
    public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
        JedisCongfig.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
    }
}
